package top.hudk.tank.model;

import top.hudk.tank.collider.CollisionChain;
import top.hudk.tank.config.GameConfig;
import top.hudk.tank.factory.AbstractFactory;
import top.hudk.tank.factory.DefaultFactory;
import top.hudk.tank.factory.Tank;
import top.hudk.tank.frame.AbstractGameFrame;
import top.hudk.tank.utils.FrameUtils;

import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 作者：hudk
 * 时间：2021/9/12 14:12
 * 描述：游戏应用上下文，包含游戏画面中的所有元素对象
 * 单例对象
 */
public class GameApplicationContext {


    private static GameApplicationContext instance = null;

    private GameApplicationContext() {
        if (instance != null) {
            throw new RuntimeException("本对象是单例模式，系统内不允许多出现个实例");
        }
    }

    /**
     * 返回单例
     *
     * @return
     */
    public static GameApplicationContext getInstance() {
        if (instance == null) {
            synchronized (GameApplicationContext.class) {
                if (instance == null) {
                    instance = new GameApplicationContext();
                    instance.initialization();
                    return instance;
                }
            }
        }
        return instance;
    }


    /**
     * 游戏元素工厂
     */
    private AbstractFactory factory = DefaultFactory.getInstance();

    /**
     * 主坦克
     */
    private Tank myTank = factory.createGoodTank();

    /**
     * 游戏界面元素类集合
     */
    private List<GameObject> objects = new ArrayList<>();

    /**
     * 等待出发的敌方坦克
     */
    private List<Tank> badTanksWaitForGo = new LinkedList<>();

    /**
     * 碰撞处理链条（责任链模式）
     */
    private CollisionChain colliderChain = new CollisionChain();


    /**
     * 初始化，加载界面中的坦克
     */
    public void initialization() {
        //初始我方坦克
        add(myTank);
        //界面中允许的最大坦克数量
        int maxTankNumb = FrameUtils.allowMaxTankNumb();
        int tankNumb = Math.min(GameConfig.TANK_NUMBER, maxTankNumb);
        for (int i = 0; i < tankNumb; i++) {
            Tank badTank = factory.createBadTank();
            add(badTank);
            badTanksWaitForGo.add(badTank);
        }
    }



    //绘制界面所有元素
    public void paint(Graphics g, AbstractGameFrame gameFrame) {
        //绘制所有元素
        for (int i = 0; i < objects.size(); i++) {
            objects.get(i).paint(g, gameFrame);
        }
        //用责任链模式，处理元素之间的碰撞逻辑
        for (int i = 0; i < objects.size(); i++) {
            for (int j = i + 1; j < objects.size(); j++) {
                colliderChain.collision(objects.get(i), objects.get(j));
            }
        }
        //敌方坦克逐一出发
        FrameUtils.badTanksWaitForGoOneByOne(badTanksWaitForGo, objects);
    }


    public AbstractFactory getFactory() {
        return factory;
    }

    public void setFactory(AbstractFactory factory) {
        this.factory = factory;
    }

    public Tank getMyTank() {
        return myTank;
    }

    public void setMyTank(Tank myTank) {
        this.myTank = myTank;
    }

    public void add(GameObject object) {
        this.objects.add(object);
    }

    public void remove(GameObject object) {
        this.objects.remove(object);
    }
}
